﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;
using System.Runtime.InteropServices;
using System.Xml;

//this will load the collision map, linked to the visual map loaded.
namespace MyImaginaryFriends_Redux.Screens.GamePlayScreen_Classes
{
    class TileMap_Colliding
    {
        static string BasePath = "Content/GameplayScreenContent/TileMapContent/CollisionMaps/";

        public CollidingTile[,] Tiles;
        

        Dictionary<string, Vector2> PlayerSpawnPoints;
      

        List<EnemyEntity> Enemies;
        List<CollectableEntity> Collectables;
        List<PushableEntity> Pushables;
        
        bool isLampKeyCollected = false;
        bool isMusicBoxCollected = false;
        bool isEnemyKeyCollected = false;

        public string loadedMapGrab;

        public TileMap_Colliding()
        {
            PlayerSpawnPoints = new Dictionary<string, Vector2>();
            Enemies = new List<EnemyEntity>();
            Collectables = new List<CollectableEntity>();
            Pushables = new List<PushableEntity>();
           
        }

        public bool LoadContent(ContentManager content, string currentMapLoaded, bool isGateActive, bool playerHasEnemyKey)
        {
            PlayerSpawnPoints = new Dictionary<string, Vector2>();
            Enemies = new List<EnemyEntity>();
            Collectables = new List<CollectableEntity>();
            Pushables = new List<PushableEntity>();
         

            if (currentMapLoaded == "StartingRoom")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "StartingRoom_Collision.txt", isGateActive, playerHasEnemyKey))
                return true;
                else return false;
            }

            if (currentMapLoaded == "Hallway")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "RoomHallway_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            if (currentMapLoaded == "RoomA")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "RoomA_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            if (currentMapLoaded == "PaintingRoom1")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "PaintingRoom1_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            if (currentMapLoaded == "PaintingRoom2")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "PaintingRoom2_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            if (currentMapLoaded == "PaintingRoom3")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "PaintingRoom3_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            if (currentMapLoaded == "PaintingRoom4")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "PaintingRoom4_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            if (currentMapLoaded == "MusicBoxRoom")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "MusicBoxRoom_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            if (currentMapLoaded == "RoomD")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "RoomD_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }
            if (currentMapLoaded == "BlockRoom1")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "BlockRoom1_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }
            if (currentMapLoaded == "BlockRoom2")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "BlockRoom2_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            if (currentMapLoaded == "RoomB")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "RoomB_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }
            if (currentMapLoaded == "RoomC")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "RoomC_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }
            if (currentMapLoaded == "GateRoom")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "GateRoom_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }
            if (currentMapLoaded == "FriendRoom")
            {
                loadedMapGrab = currentMapLoaded;
                if (LoadTileMap(content, BasePath + "FriendRoom_Collision.txt", isGateActive, playerHasEnemyKey))
                    return true;
                else return false;
            }

            return false;
        }


        //This function loads the entire map for the area
        private bool LoadTileMap(ContentManager content, string currentMapLoaded, bool isGateActive, bool playerHasEnemyKey)
        {
            int width;
            List<string> lines = new List<string>();

            using(StreamReader reader = new StreamReader(TitleContainer.OpenStream(currentMapLoaded)))
            {
                string line = reader.ReadLine();
                width = line.Length;
               

                while (line != null)
                {
                    lines.Add(line);

                    if (line.Length != width)
                    {
                        throw new Exception(String.Format("The Length of Line {0} is different from all preceeding lines", lines.Count));
                    }

                    line = reader.ReadLine();
                }
            }

            Tiles = new CollidingTile[width, lines.Count];

            for (int y = 0; y < Tiles.GetLength(1); ++y)
            {
                for (int x = 0; x < Tiles.GetLength(0); ++x)
                {
                    char tileType = lines[y][x];

                    Tiles[x, y] = LoadTiles(content, tileType, x, y, loadedMapGrab, isGateActive, playerHasEnemyKey);
                }
            }

            return true;
        }

        //Loads a batch of tiles
        private CollidingTile LoadTiles(ContentManager content, char tileType, int x, int y, string currentMapLoaded, bool isGateActive, bool playerHasEnemyKey)
        {
            #region Start Room
            if (currentMapLoaded == "StartingRoom")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);
                    case '#':
                        return AddPlayerSpawnPoint("StartingRoom_Spawn", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.
                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);
                    case 'P':
                        return SpawnLightPushable(content, x, y);

                    #region Door logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("StartingRoom_To_Hallway", x, y);
                            return LoadTile(content, TileCollision.StartingRoom_To_Hallway);
                        }
                    
                    #endregion


                    case '?':
                        return LoadTile(content, TileCollision.BedTile);
                   
                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Hallway
            else if (currentMapLoaded == "Hallway")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("Hallway_To_StartingRoom", x, y);
                            return LoadTile(content, TileCollision.Hallway_To_StartingRoom);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("Hallway_To_RoomA", x, y);
                            return LoadTile(content, TileCollision.Hallway_To_RoomA);
                        }
                    case '3':
                        {
                            AddPlayerSpawnPoint("Hallway_To_RoomD", x, y);
                            return LoadTile(content, TileCollision.Hallway_To_RoomD);
                        }
                    case '4':
                        {
                            AddPlayerSpawnPoint("Hallway_To_RoomB", x, y);
                            return LoadTile(content, TileCollision.Hallway_To_RoomB);
                        }
                    #endregion

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case 'G':
                        {
                            if (!playerHasEnemyKey)
                                return LoadTile(content, TileCollision.Passable);
                            else
                                return LoadTile(content, TileCollision.Impassable);
                        }

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Room A
            else if (currentMapLoaded == "RoomA")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("RoomA_To_Hallway", x, y);
                            return LoadTile(content, TileCollision.RoomA_To_Hallway);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("RoomA_To_PaintingRoom1", x, y);
                            return LoadTile(content, TileCollision.RoomA_To_PaintingRoom1);
                        }
                    case '3':
                        {
                            AddPlayerSpawnPoint("RoomA_To_BlockRoom2", x, y);
                            return LoadTile(content, TileCollision.RoomA_To_BlockRoom2);
                        }

                    #endregion

                    case '0':
                        return LoadTile(content, TileCollision.RoomA_GateTrigger);

                    case 'T':
                        {
                            if (!isGateActive)
                                return LoadTile(content, TileCollision.Passable);
                            else
                                return LoadTile(content, TileCollision.Impassable);
                        }


                    //case '#':
                    //    return AddPlayerSpawnPoint("Second_Start", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.
                    
                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Painting Room1
            else if (currentMapLoaded == "PaintingRoom1")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("PaintingRoom1_To_RoomA", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom1_To_RoomA);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("PaintingRoom1_To_PaintingRoom2", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom1_To_PaintingRoom2);
                        }
                   

                    #endregion

               

                    case 'T':
                        {
                            if (!isGateActive)
                                return LoadTile(content, TileCollision.Passable);
                            else
                                return LoadTile(content, TileCollision.Impassable);
                        }


                    //case '#':
                    //    return AddPlayerSpawnPoint("Second_Start", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Painting Room2
            else if (currentMapLoaded == "PaintingRoom2")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("PaintingRoom2_To_PaintingRoom1_Fall", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom2_To_PaintingRoom1Fall);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("PaintingRoom2_to_PaintingRoom1", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom2_To_PaintingRoom1);
                        }
                    case '3':
                        {
                            AddPlayerSpawnPoint("PaintingRoom2_to_PaintingRoom3", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom2_To_PaintingRoom3);
                        }


                    #endregion



                    case 'T':
                        {
                            if (!isGateActive)
                                return LoadTile(content, TileCollision.Passable);
                            else
                                return LoadTile(content, TileCollision.Impassable);
                        }


                    //case '#':
                    //    return AddPlayerSpawnPoint("Second_Start", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Painting Room3
            else if (currentMapLoaded == "PaintingRoom3")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("PaintingRoom3_To_PaintingRoom2_Fall", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom3_To_PaintingRoom2Fall);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("PaintingRoom3_to_PaintingRoom1", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom3_To_PaintingRoom1);
                        }
                    case '3':
                        {
                            AddPlayerSpawnPoint("PaintingRoom3_To_GateRoom", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom3_To_GateRoom);
                        }


                    #endregion



                    case 'T':
                        {
                            if (!isGateActive)
                                return LoadTile(content, TileCollision.Passable);
                            else
                                return LoadTile(content, TileCollision.Impassable);
                        }


                    //case '#':
                    //    return AddPlayerSpawnPoint("Second_Start", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Painting Room4
            else if (currentMapLoaded == "PaintingRoom4")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("PaintingRoom4_to_GateRoom", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom4_To_GateRoom);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("PaintingRoom4_To_MusicBoxRoom", x, y);
                            return LoadTile(content, TileCollision.PaintingRoom4_To_MusicBoxRoom);
                        }
                    

                    #endregion

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region MusicBoxRoom
            else if (currentMapLoaded == "MusicBoxRoom")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("MusicBoxRoom_To_RoomA", x, y);
                            return LoadTile(content, TileCollision.MusicBoxRoom_To_RoomA);
                        }

                    #endregion

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Room D
            else if (currentMapLoaded == "RoomD")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("RoomD_To_Hallway", x, y);
                            return LoadTile(content, TileCollision.RoomD_To_Hallway);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("RoomD_To_BlockRoom1", x, y);
                            return LoadTile(content, TileCollision.RoomD_To_BlockRoom1);
                        }
                    #endregion


                    case '+':
                        {
                            return LoadTile(content, TileCollision.RoomD_PlateTrigger_To_BlockRoom1Door);
                        }
                    

                   
                    
                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }

            #endregion

            #region BlockRoom1
            else if (currentMapLoaded == "BlockRoom1")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("BlockRoom1_To_RoomD", x, y);
                            return LoadTile(content, TileCollision.BlockRoom1_To_RoomD);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("BlockRoom1_To_BlockRoom2", x, y);
                            return LoadTile(content, TileCollision.BlockRoom1_To_BlockRoom2);
                        }
                   
                    #endregion

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case 'G':
                        {
                            if (true)
                                return LoadTile(content, TileCollision.Passable);
                            else
                                return LoadTile(content, TileCollision.Impassable);
                        }

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region BlockRoom2
            else if (currentMapLoaded == "BlockRoom2")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("BlockRoom2_To_BlockRoom1", x, y);
                            return LoadTile(content, TileCollision.BlockRoom2_To_BlockRoom1);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("BlockRoom2_To_RoomA", x, y);
                            return LoadTile(content, TileCollision.BlockRoom2_To_RoomA);
                        }

                    #endregion

                    case '+':
                        {
                            return LoadTile(content, TileCollision.BlockRoom2_Trigger_To_RoomAGate);
                        }

                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case 'G':
                        {
                            if (true)
                                return LoadTile(content, TileCollision.Passable);
                            else
                                return LoadTile(content, TileCollision.Impassable);
                        }

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Room B
            else if (currentMapLoaded == "RoomB")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("RoomB_To_Hallway", x, y);
                            return LoadTile(content, TileCollision.RoomB_To_Hallway);
                        }
                    case '2':
                        {
                            AddPlayerSpawnPoint("RoomB_To_RoomC", x, y);
                            return LoadTile(content, TileCollision.RoomB_To_RoomC);
                        }
                    #endregion

                    case '+':
                        return LoadTile(content, TileCollision.RoomB_DoorTrigger);

                    //case '#':
                    //    return AddPlayerSpawnPoint("Second_Start", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.
                    
                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }
            #endregion

            #region Room C

            else if (currentMapLoaded == "RoomC")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("RoomC_To_RoomB", x, y);
                            return LoadTile(content, TileCollision.RoomC_To_RoomB);
                        }
                    #endregion

                    //case '#':
                    //    return AddPlayerSpawnPoint("Second_Start", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.
                    
                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);

                    case 'E':
                        return SpawnEnemyKey(content, x, y);

                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }

            #endregion

            #region Gate Room

            else if (currentMapLoaded == "GateRoom")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("GateRoom_To_PaintingRoom4", x, y);
                            return LoadTile(content, TileCollision.GateRoom_To_PaintingRoom4);
                        }
                   
                    #endregion

                    case 'l':
                        return LoadTile(content, TileCollision.GateRoom_LeverTrigger);

                    //case '#':
                    //    return AddPlayerSpawnPoint("Second_Start", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.
                    
                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }

            #endregion

            #region Friend Room

            else if (currentMapLoaded == "FriendRoom")
            {
                switch (tileType)
                {
                    case '.':
                        return LoadTile(content, TileCollision.Passable);
                    case '_':
                        return LoadTile(content, TileCollision.Impassable);
                    case '-':
                        return LoadTile(content, TileCollision.Platform);
                    case '↗':
                        return LoadTile(content, TileCollision.DiagonalRightStairs);
                    case '↖':
                        return LoadTile(content, TileCollision.DiagonalLeftStairs);

                    #region Door Logic
                    case '1':
                        {
                            AddPlayerSpawnPoint("FriendRoom_To_RoomD", x, y);
                            return LoadTile(content, TileCollision.FriendRoom_To_RoomD);
                        }
                    #endregion

                    //case '#':
                    //    return AddPlayerSpawnPoint("Second_Start", x, y);//this may have to change as well, depenging on what level the player is, etc. same idea as the player spawn command.
                    
                    case 'H':
                        return LoadTile(content, TileCollision.Ladder);

                    case '$':
                        if (isEnemyKeyCollected)
                        {
                            return SpawnMannequin(content, x, y);
                        }
                        else
                            return LoadTile(content, TileCollision.Passable);
                    case 'x':
                        if (!isMusicBoxCollected)
                        {
                            return SpawnMusicBox(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case '%':
                        if (!isLampKeyCollected)
                        {
                            return SpawnLampKey(content, x, y);
                        }
                        else return LoadTile(content, TileCollision.Passable);
                    case 'P':
                        return SpawnLightPushable(content, x, y);


                    default:
                        throw new NotSupportedException(String.Format("The Character '{0}' at {1}, {2}, is unsupported", tileType, x, y));
                }
            }

            #endregion

            return LoadTile(content, TileCollision.Passable);
            
        }

        //Loads an individual tile
        private CollidingTile LoadTile(ContentManager content,TileCollision collision)
        {
            return new CollidingTile(collision);
        }

        private CollidingTile AddPlayerSpawnPoint(string point, int x, int y)
        {
            PlayerSpawnPoints.Add(point, new Vector2(x, y));

            return new CollidingTile(TileCollision.SpawnPoint);
        }

        public Vector2 GetPlayerSpawnPoint(string point)
        {
            return PlayerSpawnPoints[point];
        }

        private CollidingTile SpawnMannequin(ContentManager content, int x, int y)
        {
            Enemies.Add(new EnemyEntity(content, new Vector2(x, y), EnemyType.Mannequin));

            return new CollidingTile(TileCollision.SpawnPoint);
        }

        private CollidingTile SpawnLightPushable(ContentManager content, int x, int y)
        {
            Pushables.Add(new PushableEntity(content, new Vector2(x, y), BoxType.LightObject));

            return new CollidingTile(TileCollision.SpawnPoint);
        }

        private CollidingTile SpawnMusicBox(ContentManager content, int x, int y)
        {
            Collectables.Add(new CollectableEntity(content, new Vector2(x, y), CollectableType.MusicBox));

            return new CollidingTile(TileCollision.SpawnPoint);
        }

        private CollidingTile SpawnLampKey(ContentManager content, int x, int y)
        {
            Collectables.Add(new CollectableEntity(content, new Vector2(x, y), CollectableType.LampKey));

            return new CollidingTile(TileCollision.SpawnPoint);
        }

        private CollidingTile SpawnEnemyKey(ContentManager content, int x, int y)
        {
            Collectables.Add(new CollectableEntity(content, new Vector2(x, y), CollectableType.KnifeKey));

            return new CollidingTile(TileCollision.SpawnPoint);
        }

        public void Update(GameTime gameTime, PlayerEntity player, InputHandler input)
        {
            isEnemyKeyCollected = player.b_hasKnifeKey;
            isLampKeyCollected = player.b_HasLampKey;
            isMusicBoxCollected = player.b_HasMusicBox;

            foreach (EnemyEntity enemy in Enemies)
            {
                enemy.Update(gameTime, this, player);
            }

            foreach (CollectableEntity collectable in Collectables)
            {
                collectable.Update(gameTime, player);
            }

            foreach (PushableEntity pushable in Pushables)
            {
                pushable.Update(gameTime, this, player, input);
            }

        }

        public TileCollision GetCollision(int x, int y)
        {
            if (x < 0 || x >= Tiles.GetLength(0))
                return TileCollision.Impassable;
            if (y < 0 || y >= Tiles.GetLength(1))
                return TileCollision.Passable;

            return Tiles[x, y].Collision;
        }

        public Rectangle GetBounds(int x, int y)
        {
            return new Rectangle(x * CollidingTile.i_TileWidth, y * CollidingTile.i_TileHeight, CollidingTile.i_TileWidth, CollidingTile.i_TileHeight);
        }

        public void DrawEnemies(SpriteBatch spriteBatch)
        {
            foreach (EnemyEntity enemy in Enemies)
            {
                enemy.Draw(spriteBatch);
            }
        }

        public void DrawCollectables(SpriteBatch spriteBatch)
        {
            foreach (CollectableEntity collectable in Collectables)
            {
                collectable.Draw(spriteBatch);
            }
        }

        public void DrawPushables(SpriteBatch spriteBatch)
        {
            foreach (PushableEntity pushable in Pushables)
            {
                pushable.Draw(spriteBatch);
            }
        }

    }
}
